package dsx.system;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;

public class ThreadExPool {

	static int totalPoolNum = 0;
	static Object syncObject = new Object();
	int poolIndex = 0;
	int threadIndex = 0;

	public ThreadExPool() {
		workMap = new HashMap<String, IThreadExWork>();
		workers = new ArrayList<WorkerThread>();
		idleWorkers = new LinkedList<WorkerThread>();
		workQueue = new LinkedList<String>();
		synchronized (syncObject) {
			poolIndex = totalPoolNum;
			totalPoolNum++;
		}
	}

	public void clear() {
		synchronized (this) {
			for (int i = 0; i < workers.size(); i++)
				workers.get(i).stopExAsync();

			while (true) {
				boolean finished = true;
				for (int i = 0; i < workers.size(); i++) {
					if (workers.get(i).running) {
						finished = false;
						break;
					}
				}
				if (finished)
					break;
				else
					ThreadEx.sleepEx(300);
			}
			workers.clear();
			idleWorkers.clear();
			workQueue.clear();
		}
	}

	// 线程池
	int maxWorkerNum = 30;
	int threadStackSize = 0;
	ArrayList<WorkerThread> workers;
	Queue<WorkerThread> idleWorkers;
	Queue<String> workQueue;

	public void setThreadStackSize(int threadStackSize) {
		this.threadStackSize = threadStackSize;
	}

	public void setMaxWorkerNum(int num) {
		synchronized (this) {
			maxWorkerNum = num;
		}
	}

	public void notify(String workType) {
		synchronized (this) {
			workQueue.offer(workType);
			WorkerThread thread = takeOneThread();
			if (thread != null)
				thread.notifyEx();
		}
	}

	String getOneWork() {
		synchronized (this) {
			return workQueue.poll();
		}
	}

	WorkerThread takeOneThread() {
		synchronized (this) {
			if (idleWorkers.size() > 0) {
				return idleWorkers.poll();
			} else {
				if (workers.size() < maxWorkerNum) {
					String newThreadName = String.format("DsxPoolThread_%d_%d", poolIndex, threadIndex);
					WorkerThread thread = new WorkerThread(null, null, newThreadName, threadStackSize);
					thread.pool = this;
					thread.setInterval(Integer.MAX_VALUE);
					thread.start();
					workers.add(thread);
					return thread;
				} else {
					return null;
				}
			}
		}
	}

	void returnOneThread(WorkerThread thread) {
		synchronized (this) {
			idleWorkers.offer(thread);
		}
	}

	// 业务处理
	HashMap<String, IThreadExWork> workMap;

	public void addWork(String workType, IThreadExWork work) {
		synchronized (workMap) {
			workMap.put(workType, work);
		}
	}

	public void removeWork(String workType) {
		synchronized (workMap) {
			workMap.remove(workType);
		}
	}

	void runWork(String workType) {
		IThreadExWork work;
		synchronized (workMap) {
			work = workMap.get(workType);
		}
		if (work != null)
			work.run();
	}

	// 工作线程定义
	class WorkerThread extends ThreadEx {

		ThreadExPool pool;

		public WorkerThread() {
			super();
		}

		public WorkerThread(ThreadGroup group, Runnable target, String name,
						long stackSize) {
			super(group, target, name, stackSize);
		}

		@Override
		protected void doInLoop() {
			while (true) {
				String workType = pool.getOneWork();
				if (workType == null) {
					break;
				}
				pool.runWork(workType);
			}
			pool.returnOneThread(this);
		}

	}

}
